'use strict';

/**
 * IPC逻辑控制器
 */
const util = require('util');
const Code = require('../common/error_code');
const Cons = require('../common/constants');
const Util = require('../utils/hobot_util');
const logger = require('../utils/logger');
const ipcModel = require('../models/ipc.model');
const guardModel = require('../models/guard.model');
const userModel = require('../models/user.model');
const pushClient = require('../utils/redis_subscribe');
const ipcUrl = require('../../config/global_config').ipc;
const httpUtil = require('../utils/http');
const classroomModel = require('../models/classroom.model');
const redisOptions = require('../../config/global_config').redis;

/**
 * 查询IPC
 */
async function query(ctx) {
    const params = ctx.request.query
    const cdt = {}
    if(params.ipc_id){
        cdt._id = params.ipc_id
    }
    if(params.d_nm){
        cdt.d_nm = params.d_nm
    }
    const ipc = await ipcModel.find(cdt);
    let rst = [];
    for (let i = 0; i < ipc.length; i++) {
        const item = ipc[i];
        let status,ip
        if(item.d_tp === Cons.IPC_TYPE_jHD23){
            status = item.device_status
            ip = item.device_ip || item.d_rt.ip
        }else{
            status = await statusIpc(item._id);
            if(status==1){
                // 除巨龙设备外其他设备异常时 不显示
                continue
            }
            ip = item.d_rt.ip
        }
        rst.push({
            ipc_id: item._id,
            ipc_name: item.d_nm,
            ipc_type: item.d_tp,
            ipc_ip: ip,
            ipc_rtsp_config: item.d_rt,
            ipc_sw_flag: item.d_sw,
            ipc_capture_status: status,
            ipc_capture_config: item.d_cp,
            d_address:item.d_address,

            device_type: item.device_type||1,
            device_num: item.device_num,
            device_group: item.device_group,
            device_uuid: item.device_uuid,
            device_mac: item.device_mac,
            device_ip: item.device_ip,
            s_n: item.s_n,
            channel_num: item.channel_num,
            web_version: item.web_version,
            core_version: item.core_version,
            version_date: item.version_date,
            http_version: item.http_version,
            http_date: item.http_date,
            register_session: item.register_session,
            alarm_switch: item.alarm_switch,
            black_alarm_switch: item.black_alarm_switch,
            white_alarm_switch: item.white_alarm_switch,
            io_switch: item.io_switch,
            io_type: item.io_type,
            alarm_duration: item.alarm_duration,
            io_status_type: item.io_status_type,
            recognition_mode: item.recognition_mode,
            similarity_set: item.similarity_set,
            alarm_start_time: item.alarm_start_time,
            alarm_end_time: item.alarm_end_time,
            subnet_mask: item.subnet_mask,
            gateway: item.gateway,
            preferred_dns: item.preferred_dns,
            standby_dns: item.standby_dns
        });
    }
    // 删除冗余的IPC，后面IPC管理服务通过API获取列表启动IPC，不再独立保存一份配置 TODO
    ctx.success(Code.RET_IPC_QUERY_OK, rst);
}

/**
 * 添加IPC
 */
async function add(ctx) {
    const params = ctx.request.body;
    // 校验参数
    if (!params.ipc_type || !params.ipc_id || !params.ipc_name
        || !params.ipc_rtsp_config || !params.ipc_capture_config) {
        return ctx.error(Code.RET_IPC_ADD_ERR_PARAM);
    }
    if (params.ipc_type !== Cons.IPC_TYPE_X1S && params.ipc_type !== Cons.IPC_TYPE_RTSP
        && params.ipc_type !== Cons.IPC_TYPE_X1 && params.ipc_type !== Cons.IPC_TYPE_DAHUA
        && params.ipc_type !== Cons.IPC_TYPE_3519 && params.ipc_type !== Cons.IPC_TYPE_jHD23 ) {
        return ctx.error(Code.RET_IPC_ADD_ERR_PARAM);
    }
    const action = params.ipc_capture_config.content.action;
    if (action && (action !== Cons.IPC_ACTION_AUTOSTART && action !== Cons.IPC_ACTION_STOP)) {
        return ctx.error(Code.RET_IPC_UPDATE_ERR_PARAM);
    }
    // 默认开启抓拍
    if (!action) {
        params.ipc_capture_config.content.action = Cons.IPC_ACTION_AUTOSTART;
    }
    // 视频流，供电视APP使用
    if (!params.ipc_rtsp_config.ip) {
        return ctx.error(Code.RET_IPC_ADD_ERR_PARAM);
    }
    const cdt = { _id: params.ipc_id };
    // 编号唯一性校验
    const ipc = await ipcModel.findOne(cdt);
    if (ipc) {
        return ctx.error(Code.RET_IPC_ADD_ERR_EXIST);
    }
    // 虚拟抓拍，(巨龙设备自己发起注册所以不校验)
    if(params.ipc_type !== Cons.IPC_TYPE_jHD23){
        const captureRst = await updateIpc(params.ipc_id, params.ipc_capture_config);
        if (captureRst !== 0) {
            return ctx.error(Code.RET_IPC_ADD_ERR_CAPTURE);
        }
    }
    // 不同的IPC不同的RTSP TODO
    if (params.ipc_type === Cons.IPC_TYPE_DAHUA) {
        params.ipc_rtsp_config.rtsp = util.format('rtsp://%s:%s@%s:%s/cam/realmonitor?channel=%s@subtype=%s',
        params.ipc_rtsp_config.account, params.ipc_rtsp_config.password, params.ipc_rtsp_config.ip,
        params.ipc_rtsp_config.port, params.ipc_rtsp_config.channel, params.ipc_rtsp_config.subtype);
    } else if (params.ipc_type === Cons.IPC_TYPE_X1) {
        params.ipc_rtsp_config.rtsp = util.format('rtsp://%s:%s/ch01.264',
        params.ipc_rtsp_config.ip, params.ipc_rtsp_config.port);
    } else if (params.ipc_type === Cons.IPC_TYPE_RTSP) {
        params.ipc_rtsp_config.rtsp = params.ipc_rtsp_config.url;
    } else {
        params.ipc_rtsp_config.rtsp = util.format('rtsp://%s:%s@%s:%s/horizonStream',
        params.ipc_rtsp_config.account, params.ipc_rtsp_config.password,
        params.ipc_rtsp_config.ip, params.ipc_rtsp_config.port);
    }

    const model = {
        _id: params.ipc_id,
        d_nm: params.ipc_name,
        d_tp: params.ipc_type,
        d_rt: params.ipc_rtsp_config,
        d_sc: params.ipc_id,
        d_sw: Cons.IPC_GUARD_STATUS_OFF,
        d_cp: params.ipc_capture_config,
        d_address: params.d_address,

        device_num: params.device_num,
        device_group: params.device_group
    };
    await ipcModel.create(model);

    // try {
    //     pushClient.subscribe(params.ipc_id);    //注册监听
    // } catch (err) {
    //     logger.logError("\n" + '===== Redis subscribe error - ' + err + ' =====' + "\n");
    // }

    ctx.success(Code.RET_IPC_ADD_OK);
}

/**
 * 修改IPC
 */
async function update(ctx) {
    const params = ctx.request.body;
    // 校验参数
    if (!params.ipc_type || !params.ipc_id || !params.ipc_name
        || !params.ipc_rtsp_config || !params.ipc_capture_config) {
        return ctx.error(Code.RET_IPC_UPDATE_ERR_PARAM);
    }
    if (params.ipc_type !== Cons.IPC_TYPE_X1S && params.ipc_type !== Cons.IPC_TYPE_RTSP
        && params.ipc_type !== Cons.IPC_TYPE_X1 && params.ipc_type !== Cons.IPC_TYPE_DAHUA
        && params.ipc_type !== Cons.IPC_TYPE_3519 && params.ipc_type !== Cons.IPC_TYPE_jHD23) {
        return ctx.error(Code.RET_IPC_UPDATE_ERR_PARAM);
    }
    const action = params.ipc_capture_config.content.action;
    if (!action || (action !== Cons.IPC_ACTION_AUTOSTART && action !== Cons.IPC_ACTION_STOP)) {
        return ctx.error(Code.RET_IPC_UPDATE_ERR_PARAM);
    }

    // 视频流，供电视APP使用
    if (!params.ipc_rtsp_config.ip) {
        return ctx.error(Code.RET_IPC_UPDATE_ERR_PARAM);
    }

    const cdt = { _id: params.ipc_id };
    // 编号存在性校验
    const ipc = await ipcModel.findOne(cdt);
    if (!ipc) {
        return ctx.error(Code.RET_IPC_UPDATE_ERR_NOT_EXIST);
    }

    // 虚拟抓拍，(巨龙设备自己发起注册所以不校验)
    if(params.ipc_type !== Cons.IPC_TYPE_jHD23){
        const captureRst = await updateIpc(params.ipc_id, params.ipc_capture_config);
        if (captureRst !== 0) {
            return ctx.error(Code.RET_IPC_ADD_ERR_CAPTURE);
        }
    }

    // 不同的IPC不同的RTSP TODO
    if (params.ipc_type === Cons.IPC_TYPE_DAHUA) {
        params.ipc_rtsp_config.rtsp = util.format('rtsp://%s:%s@%s:%s/cam/realmonitor?channel=%s@subtype=%s',
        params.ipc_rtsp_config.account, params.ipc_rtsp_config.password, params.ipc_rtsp_config.ip,
        params.ipc_rtsp_config.port, params.ipc_rtsp_config.channel, params.ipc_rtsp_config.subtype);
    } else if (params.ipc_type === Cons.IPC_TYPE_X1) {
        params.ipc_rtsp_config.rtsp = util.format('rtsp://%s:%s/ch01.264',
        params.ipc_rtsp_config.ip, params.ipc_rtsp_config.port);
    } else if (params.ipc_type === Cons.IPC_TYPE_RTSP) {
        params.ipc_rtsp_config.rtsp = params.ipc_rtsp_config.url;
    } else {
        params.ipc_rtsp_config.rtsp = util.format('rtsp://%s:%s@%s:%s/horizonStream',
        params.ipc_rtsp_config.account, params.ipc_rtsp_config.password,
        params.ipc_rtsp_config.ip, params.ipc_rtsp_config.port);
    }

    const model = {
        d_nm: params.ipc_name,
        d_rt: params.ipc_rtsp_config,
        d_cp: params.ipc_capture_config,
        d_address: params.d_address,

        device_type: params.device_type||1,
        device_num: params.device_num,
        device_group: params.device_group
    };
    await ipcModel.update(cdt, model);
    ctx.success(Code.RET_IPC_UPDATE_OK);
}

/**
 * 删除IPC
 */
async function del(ctx) {
    const params = ctx.request.body;
    // 校验参数
    if (!params.ipc_id) {
        return ctx.error(Code.RET_IPC_DEL_ERR_PARAM);
    }

    const cdt = { _id: params.ipc_id };
    // 编号唯一性校验
    const ipc = await ipcModel.findOne(cdt);
    if (!ipc) {
        return ctx.error(Code.RET_IPC_DEL_ERR_NOT_EXIST);
    }
    // 删除虚拟抓拍,(巨龙设备自己发起注册所以不校验)
    if(ipc.d_tp !== Cons.IPC_TYPE_jHD23){
        const captureRst = await deleteIpc(params.ipc_id);
        if (captureRst !== 0) {
            return ctx.error(Code.RET_IPC_DEL_ERR_CAPTURE);
        }
    }else{
        // 删除巨龙设备
        await ipcModel.deleteOne(cdt);
        // 从绑定该设备的教室中移除
        if(ipc.classroom_id){
            const classroom = await classroomModel.findById(ipc.classroom_id)
            if(classroom){
                const newRelated_devices =  classroom.related_devices.filter(item=>{
                    return item.device_id!== params.ipc_id
                })
                await classroomModel.updateOne({
                    _id:ipc.classroom_id
                },{
                    related_devices:newRelated_devices
                })
            }
        }
    }
    // 删除IPC基本配置
    await ipcModel.remove(cdt);
    // 删除门禁
    await delGuard(params.ipc_id);
    // 注销监听
    // try {
    //     pushClient.unsubscribe(params.ipc_id);
    // } catch (err) {
    //     logger.logError("\n" + '===== Redis subscribe error - ' + err + ' =====' + "\n");
    // }

    ctx.success(Code.RET_IPC_DEL_OK);
}

/**
 * 重启IPC
 */
async function restart(ctx) {
    const isDev = ctx.request.host.indexOf('localhost')>-1
    const params = ctx.request.body;
    // 校验参数
    if (!params.ipc_id) {
        return ctx.error(Code.RET_IPC_RESTART_ERR_PARAM);
    }

    const cdt = { _id: params.ipc_id };
    // 编号唯一性校验
    const ipc = await ipcModel.findOne(cdt);
    if (!ipc) {
        return ctx.error(Code.RET_IPC_RESTART_ERR_NOT_EXIST);
    }
    if(ipc.d_tp === Cons.IPC_TYPE_jHD23){
        // 巨龙设备重启
        const jlParams = {
            Name: 'restartRequest',
            Session:ipc.register_session,
            TimeStamp:Math.floor(+new Date()/1000),
            UUID:ipc.device_uuid,
            ip:ipc.device_ip
        }
        try{
            await ipcModel.findOneAndUpdate(cdt,{device_status:2})
            const res = await httpUtil.post(`http://${isDev?jlParams.ip:'127.0.0.1'}:8011/Request`,jlParams)
            if(res && res.Code === 1) {
                return ctx.success(Code.REQUEST_SUCCESS('操作成功，即将重启'))
            }else{
                await ipcModel.findOneAndUpdate(cdt,{device_status:1})
                return ctx.error(Code.REQUEST_ERROR('重启失败，请检查设备连接是否正常'))
            }
        }catch(err){
            await ipcModel.findOneAndUpdate(cdt,{device_status:1})
            return ctx.error(Code.REQUEST_ERROR('重启失败'))
        }
    }else{
        const captureRst = await restartIpc(params.ipc_id);
        if (captureRst !== 0) {
            return ctx.error(Code.RET_IPC_RESTART_ERR_CAPTURE);
        }
        ctx.success(Code.RET_IPC_RESTART_OK);
    }
}

/**
 * 停止IPC
 */
async function stop(ctx) {
    const params = ctx.request.body;
    // 校验参数
    if (!params.ipc_id) {
        return ctx.error(Code.RET_IPC_STOP_ERR_PARAM);
    }

    const cdt = { _id: params.ipc_id };
    // 编号唯一性校验
    const ipc = await ipcModel.findOne(cdt);
    if (!ipc) {
        return ctx.error(Code.RET_IPC_STOP_ERR_NOT_EXIST);
    }

    const captureRst = await stopIpc(params.ipc_id);
    if (captureRst !== 0) {
        return ctx.error(Code.RET_IPC_STOP_ERR_CAPTURE);
    }

    ctx.success(Code.RET_IPC_STOP_OK);
}

/**
 * 查看门禁配置
 */
async function query_guard(ctx) {
    const params = ctx.request.query;
    // 校验参数
    if (!params.guard_id) {
        return ctx.error(Code.RET_GUARD_QUERY_ERR_PARAM);
    }

    const guard = await guardModel.findOne({ _id: params.guard_id });
    let sw_ip, sw_port, sw_channel, sw_duration;
    if (guard && guard.g_sw) {
        const options = guard.g_sw.split('-');
        if (options.length > 0) {
            sw_ip = options[0];
            if (options.length > 1) {
                sw_port = options[1];
            }
            if (options.length > 2) {
                const sw = options[2].split(':');
                sw_channel = sw[0];
                sw_duration = Number(sw[1]) + '';
            }
        }
        ctx.success(Code.RET_GUARD_QUERY_OK, {
            ipc_sw_ip: sw_ip,
            ipc_sw_port: sw_port,
            ipc_sw_channel: sw_channel,
            ipc_sw_duration: sw_duration
        });
    } else {
        ctx.error(Code.RET_GUARD_QUERY_ERR_NOT_EXIST);
    }
}

/**
 * 设置/删除门禁
 */
async function do_guard(ctx) {
    const params = ctx.request.body;
    // 校验参数
    if (!params.ipc_id) {
        return ctx.error(Code.RET_GUARD_SET_ERR_PARAM);
    }
    if (params.ipc_sw_ip && (!params.ipc_sw_port || !params.ipc_sw_channel || !params.ipc_sw_duration)) {
        return ctx.error(Code.RET_GUARD_SET_ERR_PARAM);
    }

    // 门禁控制的id和IPC的id是一致的
    const cdt = { _id: params.ipc_id };
    // ipc_id存在性校验
    const ipc = await ipcModel.findOne(cdt);
    if (!ipc) {
        return ctx.error(Code.RET_GUARD_SET_ERR_NOT_EXIST);
    }

    // 设为门禁
    if (params.ipc_sw_ip) {
        const gModel = {
            g_sw: util.format('%s-%s-%s:%s', params.ipc_sw_ip, params.ipc_sw_port,
                params.ipc_sw_channel, Util.paddingLeft(params.ipc_sw_duration, 2))
        };
        // 初始门禁
        const guard = await guardModel.findOne(cdt);
        if (!guard) {
            gModel._id = params.ipc_id;

            let arr = [];
            // 周日
            arr.push({ week: "0", value: 0 });
            // 周一
            arr.push({ week: "1", value: 1 });
            // 周二
            arr.push({ week: "2", value: 1 });
            // 周三
            arr.push({ week: "3", value: 1 });
            // 周四
            arr.push({ week: "4", value: 1 });
            // 周五
            arr.push({ week: "5", value: 1 });
            // 周六
            arr.push({ week: "6", value: 0 });
            gModel.p_wk = arr;

            // 获得门禁监听频道
            let guard_channel = '';
            const ipc = await ipcModel.findOne(cdt);
            if (ipc) {
                guard_channel = ipc.d_sc;
            }
            gModel.g_ch = guard_channel;

            //gModel.g_st = Cons.SW_TYPE_HUAQIANG;
            gModel.g_st = Cons.SW_TYPE_BOXINI;
            gModel.p_fr = Cons.GUARG_TIME_FROM;
            gModel.p_to = Cons.GUARG_TIME_TO;

            await guardModel.create(gModel);
            // 更新门禁标志位
            await ipcModel.update(cdt, { d_sw: Cons.IPC_GUARD_STATUS_ON });

        } else {
            await guardModel.update(cdt, gModel);
        }

        ctx.success(Code.RET_GUARD_SET_OK);
    }
    // 删除门禁功能
    else {
        await delGuard(params.ipc_id);
        // 更新门禁标志位
        await ipcModel.update(cdt, { d_sw: Cons.IPC_GUARD_STATUS_OFF });

        ctx.success(Code.RET_GUARD_DEL_OK);
    }
}

/**
 * 查询IPC（APP专供）
 */
async function query_ipcs(ctx) {
    const ipc = await ipcModel.find();

    let rst = [];
    for (let i = 0; i < ipc.length; i++) {
        const item = ipc[i];
        rst.push({
            ipc_id: item._id,
            ipc_name: item.d_nm,
            ipc_rtsp: item.d_rt.rtsp,
            ipc_channel: item.d_sc
        });
    }
    ctx.success(Code.RET_APP_QUERY_IPCS_OK, { pub_server_config: redisOptions, ipc_list: rst });
}

/**
 * 添加和更新虚拟抓拍
 * @param ipcId
 * @param json
 * @returns {Promise<void>}
 */
async function updateIpc(ipcId, json) {
    // const ipcConfig = json.IpcConfig;
    // const sdkConfig = json.SdkConfig;
    // // const ipcConfig = JSON.parse(json).IpcConfig;
    // // const sdkConfig = JSON.parse(json).SdkConfig;
    //
    // const ipc_capture_config = {
    //     target: 'ipc',
    //     content: {
    //         name: ipcId,
    //         IpcConfig: {
    //             dh_info: {
    //                 ip: ipcConfig.ip,
    //                 port: Number(ipcConfig.port),
    //                 username: ipcConfig.username,
    //                 password: ipcConfig.password
    //             }
    //         },
    //         SdkConfig: {
    //             source_config: {
    //                 width: Number(sdkConfig.width),
    //                 height: Number(sdkConfig.height),
    //                 face_path: 'tmp_yuv_' + ipcId,
    //                 cloud_service_base_url: sdkConfig.cloud_service_base_url,
    //                 cloud_face_recog_api: sdkConfig.cloud_face_recog_api,
    //                 face_filter: {
    //                     pose_low: Number(sdkConfig.face_filter.pose_low),
    //                     pose_high: Number(sdkConfig.face_filter.pose_high),
    //                     blur_low: Number(sdkConfig.face_filter.blur_low),
    //                     blur_high: Number(sdkConfig.face_filter.blur_high),
    //                     width_low: Number(sdkConfig.face_filter.width_low),
    //                     width_high: Number(sdkConfig.face_filter.width_high),
    //                     height_low: Number(sdkConfig.face_filter.height_low),
    //                     height_high: Number(sdkConfig.face_filter.height_high),
    //                     width_bound_thr: Number(sdkConfig.face_filter.width_bound_thr),
    //                     height_bound_thr: Number(sdkConfig.face_filter.height_bound_thr)
    //                 },
    //                 face_snap: {
    //                     snapshot_mode: Number(sdkConfig.face_snap.snapshot_mode),
    //                     max_track_frame_num: Number(sdkConfig.face_snap.max_track_frame_num),
    //                     track_timeout: Number(sdkConfig.face_snap.track_timeout),
    //                     report_thresh: Number(sdkConfig.face_snap.report_thresh)
    //                 },
    //                 device_id: ipcId
    //             }
    //         }
    //     }
    // };
    const rst = await httpUtil.post(ipcUrl.update, json);
    return rst.status_code;
}

/**
 * 删除虚拟抓拍
 */
async function deleteIpc(ipcId) {
    const rst = await httpUtil.post(ipcUrl.delete, { target: 'ipc', content: { name: ipcId } });
    return rst.status_code;
}

/**
 * 查询IPC状态
 */
async function statusIpc(ipcId) {
    let rst = Cons.IPC_STATUS_ERR;
    try{
        const ipcStatus = await httpUtil.post(ipcUrl.status, { target: 'ipc', content: { name: ipcId } });
        if (ipcStatus && ipcStatus.status_code === 0 && ipcStatus.status && ipcStatus.status.indexOf('running') >= 0) {
            rst = Cons.IPC_STATUS_OK;
        }
    }catch(err){
        rst = Cons.IPC_STATUS_ERR;
    }
    return rst;
}

/**
 * 启动IPC
 */
async function startIpc(ipcId) {
    const rst = await httpUtil.post(ipcUrl.start, { target: 'ipc', content: { name: ipcId } });
    return rst.status_code;
}

/**
 * 停止IPC
 */
async function stopIpc(ipcId) {
    const rst = await httpUtil.post(ipcUrl.stop, { target: 'ipc', content: { name: ipcId } });
    return rst.status_code;
}

/**
 * 重启IPC
 */
async function restartIpc(ipcId) {
    const rst = await httpUtil.post(ipcUrl.restart, { target: 'ipc', content: { name: ipcId } });
    return rst.status_code;
}

async function delGuard(ipcId) {
    const cdt = { _id: ipcId };
    // 获得门禁的订阅channel，因为需要注销
    const guard = await guardModel.findOne(cdt);
    if (!guard) {
        return;
    }

    // 删除门禁数据
    await guardModel.remove(cdt);
}

/**
 * 获取IPC列表，用于识别记录中的展示
 */
async function getIpcList() {
    const ipc = await ipcModel.find({}, { _id: 1, d_nm: 1 });
    let rst = [];
    for (let item of ipc) {
        rst.push({ value: item._id, label: item.d_nm });
    }
    return rst;
}



// 巨龙设备-报警设置
async function update_alarm(ctx){
    const params = ctx.request.body
    try{
        const alarmParams = {
            device_uuid:'uuid',
            alarm_switch: '报警开关',
            black_alarm_switch: '黑名单报警开关',
            white_alarm_switch: '白名单报警开关',
            io_switch: 'IO输出',
            io_type: 'io输入类型，1持续输出，2脉冲输出',
            alarm_duration: '报警持续时间(s)',
            io_status_type: 'IO输出状态类型，1常开，2常闭',
            recognition_mode: '识别模式，1一直识别，2次数识别，3单张识别',
            similarity_set: '比对相似度, 1~100',
            alarm_start_time: '布防时间段',
            alarm_end_time: '布防时间段',
        }
        const schema = Object.keys(alarmParams)
        if(!params || typeof params !=='object') return ctx.error(Code.REQUEST_ERROR('请填写设备参数'))
        for(let key of schema){
            if(params[key]==undefined||params[key]===''){
                const msg = alarmParams[key]
                return ctx.error(Code.REQUEST_ERROR(msg))
            }
        }
        const rangeRegex = /\d{2}:\d{2}/
        if(!rangeRegex.test(params.alarm_start_time)||!rangeRegex.test(params.alarm_end_time)){
            return ctx.error(Code.REQUEST_ERROR('布防时间段时间格式错误'))
        }
        const data = await deviceModel.findOneAndUpdate({device_uuid:params.device_uuid},params)
        if(data){
            return ctx.success(Code.REQUEST_SUCCESS('更新成功'))
        }
        return ctx.error(Code.REQUEST_ERROR('未找到对应的设备'))
    }catch(err){
        console.log(err)
        return ctx.error(Code.REQUEST_ERROR('更新失败'))
    }
}


// 巨龙设备-网络设置
async function update_net(ctx){
    const params = ctx.request.body
    try{
        const netParams = {
            device_uuid:'uuid',
            subnet_mask: '子网掩码',
            gateway: '网关',
            preferred_dns: '首选DNS地址',
            standby_dns: '备用DNS地址'
        }
        const schema = Object.keys(netParams)
        if(!params || typeof params !=='object') return ctx.error(Code.REQUEST_ERROR('请填写设备参数'))
        for(let key of schema){
            if(params[key]==undefined||params[key]===''){
                const msg = netParams[key]
                return ctx.error(Code.REQUEST_ERROR(msg))
            }
        }
        const ipRegex = /\d{3}\.\d{3}\.\d{1,3}\.\d{1,3}/
        if(!ipRegex.test(params.device_ip)) return ctx.error(Code.REQUEST_ERROR('ip地址格式不规范'))
        const data = await deviceModel.findOneAndUpdate({device_uuid:params.device_uuid},params)
        if(data){
            return ctx.success(Code.REQUEST_SUCCESS('更新成功'))
        }
        return ctx.error(Code.REQUEST_ERROR('未找到对应的设备'))
    }catch(err){
        console.log(err)
        return ctx.error(Code.REQUEST_ERROR('更新失败'))
    }
}

// 查看巨龙设备-底库列表
async function getPhotoLibrary(ctx){
    const isDev = ctx.request.host.indexOf('localhost')>-1
    const params = ctx.request.body
    // 校验参数
    if (!params.ipc_id || !params.page_size || !params.page_num) {
        return ctx.error(Code.REQUEST_ERROR('参数错误'));
    }
    const device = await ipcModel.findOne({_id:params.ipc_id,d_tp:Cons.IPC_TYPE_jHD23})
    if(!device){
        return ctx.error(Code.REQUEST_ERROR('该设备底库不存在'))
    }
    const queryParams = {
        Name: 'personListRequest',
        Session:device.register_session,
        TimeStamp:Math.floor(+new Date()/1000),
        UUID:device.device_uuid,
        ip:device.device_ip,
        Data:{
            Action:'getPersonList',
            PersonType:2,
            PageNo:params.page_num||1,
            PageSize:params.page_size||10,
        },
    }
    try{
        const res = await httpUtil.postWithTimeout(`http://${isDev?queryParams.ip:'127.0.0.1'}:8011/Request`,queryParams, 1000*20, '查看失败，请检查设备连接')

        if(res && res.Code === 1) {
            let result = res.Data.PersonList||[];
            result.forEach(item=>{
                item.belongDeviceId = params.ipc_id
                item.belongDeviceName = device.d_nm
                item.belongDeviceNum = device.device_num
                item.group_name = device.group_name
                item.campus_name = device.campus_name
                item.class_name = device.class_name
            })
            return ctx.success(Code.REQUEST_SUCCESS('查看成功'),{
                page_num:res.Data.PageNo,
                page_size:res.Data.PageSize,
                total:res.Data.PersonCount,
                result
            })
        }else{
            return ctx.error(Code.REQUEST_ERROR(res.msg||'查看失败'))
        }
    }catch(err){
        console.log(err)
        return ctx.error(Code.REQUEST_ERROR('查看失败，请检查设备是否正常连接'))
    }
}

// 查看巨龙设备-学生底库信息
async function getStudentLibraryInfo(ctx){
    const isDev = ctx.request.host.indexOf('localhost')>-1
    const params = ctx.request.body
    // 校验参数
    if (!params.ipc_id || !params.student_id) {
        return ctx.error(Code.REQUEST_ERROR('参数错误'));
    }
    const device = await ipcModel.findOne({_id:params.ipc_id,d_tp:Cons.IPC_TYPE_jHD23})
    if(!device){
        return ctx.error(Code.REQUEST_ERROR('该设备底库不存在'))
    }
    const queryParams = {
        Name: 'personListRequest',
        Session:device.register_session,
        TimeStamp:Math.floor(+new Date()/1000),
        UUID:device.device_uuid,
        ip:device.device_ip,
        Data:{
            Action:'getPerson',
            PersonType:2,
            PersonId:params.student_id,
            GetPhoto:1
        },
    }
    try{
        const res = await httpUtil.postWithTimeout(`http://${isDev?queryParams.ip:'127.0.0.1'}:8011/Request`,queryParams, 1000*20, '查看失败，请检查设备连接')
        if(res && res.Code === 1) {
            return ctx.success(Code.REQUEST_SUCCESS('查看成功'),res.Data)
        }else{
            return ctx.error(Code.REQUEST_ERROR(res.msg||'查看失败'))
        }
    }catch(err){
        console.log(err)
        return ctx.error(Code.REQUEST_ERROR('查看失败，请检查设备是否正常连接'))
    }
}

// 更新巨龙设备-学生底库信息
async function updateStudentLibraryInfo(ctx){
    const isDev = ctx.request.host.indexOf('localhost')>-1
    const params = ctx.request.body
    // 校验参数
    if (!params.ipc_id || !params._id) {
        return ctx.error(Code.REQUEST_ERROR('参数错误'));
    }
    const device = await ipcModel.findOne({_id:params.ipc_id,d_tp:Cons.IPC_TYPE_jHD23})
    if(!device){
        return ctx.error(Code.REQUEST_ERROR('该设备底库不存在'))
    }
    const queryParams = {
        Name: 'personListRequest',
        Session:device.register_session,
        TimeStamp:Math.floor(+new Date()/1000),
        UUID:device.device_uuid,
        ip:device.device_ip,
        Data:{
            Action:'editPerson',
            PersonType:2,
            PersonInfo:{
                PersonId: params._id,
                PersonName: params.u_nm,
                Sex: params.u_sx,
                IDCard: params.user_idcard,
                Nation: params.user_nation,
                Birthday: params.user_birthday,
                Phone: params.u_pn,
                Address: params.user_address,
                LimitTime: params.user_limit, 
                PersonExtension:{
                    PersonCode1: params.s_num, //学号
                    PersonCode2: params.s_school, //学校
                    PersonCode3: params.s_class, //班级
                    PersonData1: params.u_em //邮箱
                },
                PersonPhoto: params.u_hp
            }
        },
    }
    try{
        const res = await httpUtil.postWithTimeout(`http://${isDev?queryParams.ip:'127.0.0.1'}:8011/Request`,queryParams, 1000*20, '更新失败，请检查设备连接')
        if(res && res.Code === 1) {
            return ctx.success(Code.REQUEST_SUCCESS('更新成功'),res.Data)
        }else{
            return ctx.error(Code.REQUEST_ERROR(res.Message||res.msg||'更新失败'))
        }
    }catch(err){
        console.log(err)
        return ctx.error(Code.REQUEST_ERROR('更新失败，请检查设备是否正常连接'))
    }
}

// 批量更新巨龙设备-学生底库信息
async function batchUpdateStudentLibrary(ctx){
    const isDev = ctx.request.host.indexOf('localhost')>-1
    const params = ctx.request.body
    // 校验参数
    if (!params.ipc_id || !params.student_ids || !Array.isArray(params.student_ids)) {
        return ctx.error(Code.REQUEST_ERROR('参数错误'));
    }
    const device = await ipcModel.findOne({_id:params.ipc_id,d_tp:Cons.IPC_TYPE_jHD23})
    if(!device){
        return ctx.error(Code.REQUEST_ERROR('该设备底库不存在'))
    }
    const studentIds = params.student_ids
    try{
        for(let student_id of studentIds){
            const studentInfo = await userModel.findOne({_id:student_id,u_tp:5})
            if(!studentInfo){
                continue
            }
            const queryParams = {
                Name: 'personListRequest',
                Session:device.register_session,
                TimeStamp:Math.floor(+new Date()/1000),
                UUID:device.device_uuid,
                ip:device.device_ip,
                Data:{
                    Action:'editPerson',
                    PersonType:2,
                    PersonInfo:{
                        PersonId: studentInfo._id,
                        PersonName: studentInfo.u_nm,
                        Sex: params.u_sx,
                        IDCard: studentInfo.user_idcard,
                        Nation: studentInfo.user_nation,
                        Birthday: studentInfo.user_birthday,
                        Phone: studentInfo.u_pn,
                        Address: studentInfo.user_address,
                        LimitTime: studentInfo.user_limit, 
                        PersonExtension:{
                            PersonCode1: studentInfo.s_num, //学号
                            PersonCode2: studentInfo.s_school, //学校
                            PersonCode3: studentInfo.s_class, //班级
                            PersonData1: studentInfo.u_em //邮箱
                        },
                        PersonPhoto: studentInfo.u_hp
                    }
                },
            }    
            const res = await httpUtil.postWithTimeout(`http://${isDev?queryParams.ip:'127.0.0.1'}:8011/Request`,queryParams, 1000*20, '更新失败，请检查设备连接')
            if(res && res.Code === 2) {
                return ctx.error(Code.REQUEST_ERROR(res.msg||'更新失败'))
            }
        }  
        return ctx.success(Code.REQUEST_SUCCESS('更新成功'))   
    }catch(err){
        console.log(err)
        return ctx.error(Code.REQUEST_ERROR('更新失败，请检查设备是否正常连接'))
    }
}

// 删除巨龙设备-学生底库信息
async function deleteStudentLibraryInfo(ctx){
    const isDev = ctx.request.host.indexOf('localhost')>-1
    const params = ctx.request.body
    // 校验参数
    if (!params.ipc_id || !params._id) {
        return ctx.error(Code.REQUEST_ERROR('参数错误'));
    }
    const device = await ipcModel.findOne({_id:params.ipc_id,d_tp:Cons.IPC_TYPE_jHD23})
    if(!device){
        return ctx.error(Code.REQUEST_ERROR('该设备底库不存在'))
    }
    const queryParams = {
        Name: 'personListRequest',
        Session:device.register_session,
        TimeStamp:Math.floor(+new Date()/1000),
        UUID:device.device_uuid,
        ip:device.device_ip,
        Data:{
            Action:'deletePerson',
            PersonType:2,
            PersonId: params._id
        }
    }
    try{
        const res = await httpUtil.postWithTimeout(`http://${isDev?queryParams.ip:'127.0.0.1'}:8011/Request`,queryParams, 1000*20, '删除失败，请检查设备连接')
        if(res && res.Code === 1) {
            return ctx.success(Code.REQUEST_SUCCESS('删除成功'),res.Data)
        }else{
            console.log(res)
            return ctx.error(Code.REQUEST_ERROR(res.msg||res.Message||'删除失败'))
        }
    }catch(err){
        console.log(err)
        return ctx.error(Code.REQUEST_ERROR('删除失败，请检查设备是否正常连接'))
    }
}

// 批量删除巨龙设备-学生底库信息
async function batchDeleteStudentLibrary(ctx){
    const params = ctx.request.body
    // 校验参数
    if (!params.ipc_id || !params.student_ids || !Array.isArray(params.student_ids)) {
        return ctx.error(Code.REQUEST_ERROR('参数错误'));
    }
    const device = await ipcModel.findOne({_id:params.ipc_id,d_tp:Cons.IPC_TYPE_jHD23})
    if(!device){
        return ctx.error(Code.REQUEST_ERROR('该设备底库不存在'))
    }
    const studentIds = params.student_ids
    try{
        for(let student_id of studentIds){
            const queryParams = {
                Name: 'personListRequest',
                Session:device.register_session,
                TimeStamp:Math.floor(+new Date()/1000),
                UUID:device.device_uuid,
                ip:device.device_ip,
                Data:{
                    Action:'deletePerson',
                    PersonType:2,
                    PersonId: student_id
                }
            }
            const res = await httpUtil.postWithTimeout(`http://${queryParams.ip}:8011/Request`,queryParams, 1000*20, '删除失败，请检查设备连接')
            if(res && res.Code === 2) {
                return ctx.error(Code.REQUEST_ERROR(res.msg||'删除失败'))
            }
        }
        return ctx.success(Code.REQUEST_SUCCESS('删除成功'))   
    }catch(err){
        console.log(err)
        return ctx.error(Code.REQUEST_ERROR('删除失败，请检查设备是否正常连接'))
    }
}

// 清空巨龙设备-学生底库信息
async function emptyStudentLibrary(ctx){
    const isDev = ctx.request.host.indexOf('localhost')>-1
    const params = ctx.request.body
    // 校验参数
    if (!params.ipc_id) {
        return ctx.error(Code.REQUEST_ERROR('参数错误'));
    }
    const device = await ipcModel.findOne({_id:params.ipc_id,d_tp:Cons.IPC_TYPE_jHD23})
    if(!device){
        return ctx.error(Code.REQUEST_ERROR('该设备底库不存在'))
    }
    const queryParams = {
        Name: 'personListRequest',
        Session:device.register_session,
        TimeStamp:Math.floor(+new Date()/1000),
        UUID:device.device_uuid,
        ip:device.device_ip,
        Data:{
            Action:'deletePersonList',
            PersonType:2,
        }
    }
    try{
        const res = await httpUtil.postWithTimeout(`http://${isDev?queryParams.ip:'127.0.0.1'}:8011/Request`,queryParams, 1000*20, '清空失败，请检查设备连接')
        if(res && res.Code === 1) {
            return ctx.success(Code.REQUEST_SUCCESS('清空成功'),res.Data)
        }else{
            console.log(res)
            return ctx.error(Code.REQUEST_ERROR(res.msg||res.Message||'清空失败'))
        }
    }catch(err){
        console.log(err)
        return ctx.error(Code.REQUEST_ERROR('清空失败，请检查设备是否正常连接'))
    }
}


// 查询IPC
exports.query = query;
// 添加IPC
exports.add = add;
// 修改IPC
exports.update = update;
// 删除IPC
exports.delete = del;
// 重启IPC
exports.restart = restart;
// 停止IPC
exports.stop = stop;
// 查看门禁配置
exports.query_guard = query_guard;
// 设置门禁
exports.do_guard = do_guard;
// 设置门禁
exports.getIpcList = getIpcList;

// 查询IPC（APP专供）
exports.query_ipcs = query_ipcs;

// 查看巨龙设备jHD-23-底库
exports.get_photo_library = getPhotoLibrary;

// 查看巨龙设备jHD-23-学生底库信息
exports.get_student_library_info = getStudentLibraryInfo;

// 更新巨龙设备jHD-23-学生底库信息
exports.update_student_library_info = updateStudentLibraryInfo;

// 删除巨龙设备jHD-23-学生底库信息
exports.delete_student_library_info = deleteStudentLibraryInfo;

// 批量更新巨龙设备jHD-23-学生底库信息
exports.batch_update_student_library = batchUpdateStudentLibrary;

// 批量删除巨龙设备jHD-23-学生底库信息
exports.batch_delete_student_library = batchDeleteStudentLibrary;

// 清空巨龙设备jHD-23-学生底库
exports.empty_student_library = emptyStudentLibrary;